//package com.gateway;
//
//import org.springframework.cloud.gateway.filter.GatewayFilter;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
//import org.springframework.http.HttpHeaders;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Mono;
//
//import java.util.Arrays;
//import java.util.List;
//import java.util.regex.Pattern;
//
//
// public class CustomGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomGatewayFilterFactory.Config> {
//    private static final String STRIP_VERSION_KEY = "stripVersion";
//
//    private static final String LOCATION_HEADER_NAME_KEY = "locationHeaderName";
//
//    private static final String HOST_VALUE_KEY = "hostValue";
//
//    private static final String PROTOCOLS_KEY = "protocols";
//
//    private static final Pattern VERSIONED_PATH = Pattern.compile("^/v\\d+/.*");
//
//    private static final String DEFAULT_PROTOCOLS = "https?|ftps?";
//
//    private static final Pattern DEFAULT_HOST_PORT = compileHostPortPattern(
//            DEFAULT_PROTOCOLS);
//
//    private static final Pattern DEFAULT_HOST_PORT_VERSION = compileHostPortVersionPattern(
//            DEFAULT_PROTOCOLS);
//
//
//    private static Pattern compileHostPortPattern(String protocols) {
//        return Pattern.compile("(?<=^(?:" + protocols + ")://)[^:/]+(?::\\d+)?(?=/)");
//    }
//
//    private static Pattern compileHostPortVersionPattern(String protocols) {
//        return Pattern.compile(
//                "(?<=^(?:" + protocols + ")://)[^:/]+(?::\\d+)?(?:/v\\d+)?(?=/)");
//    }
//
//    @Override
//    public List<String> shortcutFieldOrder() {
//        return Arrays.asList(STRIP_VERSION_KEY, LOCATION_HEADER_NAME_KEY, HOST_VALUE_KEY,
//                PROTOCOLS_KEY);
//    }
//
//    public GatewayFilter apply(Config config) {
//        return new GatewayFilter() {
//            @Override
//            public Mono<Void> filter(ServerWebExchange exchange,
//                                     GatewayFilterChain chain) {
//                return chain.filter(exchange)
//                        .then(Mono.fromRunnable(() -> rewriteLocation(exchange, config)));
//            }
//
//        };
//    }
//
//    void rewriteLocation(ServerWebExchange exchange, Config config) {
//        final String location = exchange.getResponse().getHeaders()
//                .getFirst(config.getLocationHeaderName());
//        final String host = config.getHostValue() != null ? config.getHostValue()
//                : exchange.getRequest().getHeaders().getFirst(HttpHeaders.HOST);
//        final String path = exchange.getRequest().getURI().getPath();
//        if (location != null && host != null) {
//            final String fixedLocation = fixedLocation(location, host, path,
//                    config.getStripVersion(), config.getHostPortPattern(),
//                    config.getHostPortVersionPattern());
//            exchange.getResponse().getHeaders().set(config.getLocationHeaderName(),
//                    fixedLocation);
//        }
//    }
//
//    String fixedLocation(String location, String host, String path,
//                         CustomGatewayFilterFactory.StripVersion stripVersion, Pattern hostPortPattern,
//                         Pattern hostPortVersionPattern) {
//        final boolean doStrip = CustomGatewayFilterFactory.StripVersion.ALWAYS_STRIP.equals(stripVersion)
//                || (CustomGatewayFilterFactory.StripVersion.AS_IN_REQUEST.equals(stripVersion)
//                && !VERSIONED_PATH.matcher(path).matches());
//        final Pattern pattern = doStrip ? hostPortVersionPattern : hostPortPattern;
//        return pattern.matcher(location).replaceFirst(host);
//    }
//
//
//    public enum StripVersion {
//
//        /**
//         * Version will not be stripped, even if the original request path contains no
//         * version.
//         */
//        NEVER_STRIP,
//
//        /**
//         * Version will be stripped only if the original request path contains no version.
//         * This is the Default.
//         */
//        AS_IN_REQUEST,
//
//        /**
//         * Version will be stripped, even if the original request path contains version.
//         */
//        ALWAYS_STRIP
//
//    }
//    public static class Config {
//
//        private CustomGatewayFilterFactory.StripVersion stripVersion = CustomGatewayFilterFactory.StripVersion.AS_IN_REQUEST;
//
//        private String locationHeaderName = HttpHeaders.LOCATION;
//
//        private String hostValue;
//
//        private String protocols = DEFAULT_PROTOCOLS;
//
//        private Pattern hostPortPattern = DEFAULT_HOST_PORT;
//
//        private Pattern hostPortVersionPattern = DEFAULT_HOST_PORT_VERSION;
//
//        public CustomGatewayFilterFactory.StripVersion getStripVersion() {
//            return stripVersion;
//        }
//
//        public CustomGatewayFilterFactory.Config setStripVersion(CustomGatewayFilterFactory.StripVersion stripVersion) {
//            this.stripVersion = stripVersion;
//            return this;
//        }
//
//        public String getLocationHeaderName() {
//            return locationHeaderName;
//        }
//
//        public CustomGatewayFilterFactory.Config setLocationHeaderName(String locationHeaderName) {
//            this.locationHeaderName = locationHeaderName;
//            return this;
//        }
//
//        public String getHostValue() {
//            return hostValue;
//        }
//
//        public CustomGatewayFilterFactory.Config setHostValue(String hostValue) {
//            this.hostValue = hostValue;
//            return this;
//        }
//
//        public String getProtocols() {
//            return protocols;
//        }
//
//        public CustomGatewayFilterFactory.Config setProtocols(String protocols) {
//            this.protocols = protocols;
//            this.hostPortPattern = compileHostPortPattern(protocols);
//            this.hostPortVersionPattern = compileHostPortVersionPattern(protocols);
//            return this;
//        }
//
//        public Pattern getHostPortPattern() {
//            return hostPortPattern;
//        }
//
//        public Pattern getHostPortVersionPattern() {
//            return hostPortVersionPattern;
//        }
//
//    }
//
//}
